package org.apnprovider.publisher;
import org.apnprovider.Configuration;
import org.apnprovider.Device;
import org.apnprovider.DeviceStorage;
import javapns.Push;
import javapns.communication.exceptions.CommunicationException;
import javapns.communication.exceptions.KeystoreException;

/**
 * Class to implement Publisher interface 
 * @see Publisher
 * 
 * @author Alexey Palamarchuk (slonnik@gmail.com)
 *
 */
final public class PublisherJPN {
	
	/** underlying JPN transport*/
	final private PublisherJPNService service;
	/** storage*/
	private final DeviceStorage storage;
	/** password*/
	private final String password;
	/** path to keystore*/
	private final String keystore;
	/** flag to indicate if we connect under prod*/
	private final boolean isProd;
	
	final static String PUBLISHER = "publisher";
	final static String PUBLISHER_PASSWORD = PUBLISHER + ".password";
	final static String PUBLISHER_KEYSTORE = PUBLISHER + ".keystore";
	final static String PUBLISHER_PROD = PUBLISHER + ".prod";
	
	/**
	 * ctor
	 * @param storage - device storage
	 * @param config - common configuration
	 */
	public PublisherJPN(DeviceStorage storage, Configuration config)
	{
		this(new PublisherJPNService()
		{
			public void alert(String message, String keystore, String password, boolean isProd, String token) 
				throws CommunicationException, KeystoreException 
			{
				Push.alert(message, keystore, password, isProd, token);
			};
		}, storage, config);
	}
	
	/**
	 * ctor
	 * @param service - JPN transport
	 * @param storage - device storage
	 * @param config - common configuration
	 * 
	 * This ctor is mainly used by unit tests
	 */
	PublisherJPN(PublisherJPNService service, DeviceStorage storage, Configuration config)
	{

		this.storage = storage;
		password = config.get(PUBLISHER_PASSWORD);
		if(password == null)
		{
			throw new IllegalArgumentException("Password is not defined for APN service.");
		}
		keystore = config.get(PUBLISHER_KEYSTORE);
		if(keystore == null)
		{
			throw new IllegalArgumentException("Keystore is not defined for APN service.");
		}
		isProd = Boolean.parseBoolean(config.get(PUBLISHER_PROD, "false"));
		
		this.service = service;
	}
	
	/**
	 * push notification to devices
	 * @param message - message to be pushed
	 * @param key - provider key
	 * 
	 */
	public void push(String message, String key) throws PublisherException
	{
		for(Device device : storage.findDevicesByProviderKey(key))
		{
			try {
				service.alert(message, keystore, password, isProd, device.token());
			} catch (Exception e)
			{
				throw new PublisherException(e);
			}
		}
		
	}
}
